import urllib.request
import urllib.parse
import http.cookiejar
import json
import hashlib
import logging


class SsdevService(object):

    @classmethod
    def create(cls, client: 'SsdevClient',
               path: str,
               utils_domain_name: str = 'pay-balance-service',
               utils_service_name: str = 'rpcUtilsService'):
        rsp = client.invoke(utils_domain_name+'.'+utils_service_name, 'getServiceDesc', path)
        code = rsp['code']

    def __init__(self, client: 'SsdevClient', service_desc):
        self.client = client
        self.service_desc = service_desc

    def parse_service_desc(self):
        service_desc = self.service_desc


class SsdevClient(object):
    MY_ROLES_PATH = "/logon/myRoles"
    LOGON_LOGIN_VALIDATE = "/logon/loginValidate"
    MY_APPS = "/logon/myApps"

    def __init__(self, bbp_base_url: str, app_base_url: str):
        self.charset = 'UTF-8'
        self.bbp_base_url = bbp_base_url if not bbp_base_url.endswith('/') else bbp_base_url[:-1]
        self.app_base_url = app_base_url if not app_base_url.endswith('/') else app_base_url[:-1]
        self.token = None

        self.cookie = http.cookiejar.CookieJar()
        self.handler = urllib.request.HTTPCookieProcessor(self.cookie)
        self.opener = urllib.request.build_opener(self.handler)

    def http_request(self, url, method, headers, data):
        if data is None:
            pass
        elif isinstance(data, str):
            data = bytes(data, self.charset)
        elif isinstance(data, bytes):
            pass
        else:
            return self.http_request(url, method, headers, json.dumps(data))

        if data is None or isinstance(data, bytes):
            request = urllib.request.Request(url, headers=headers, data=data, method=method)
            with self.opener.open(request) as response:
                rsp = response.read().decode(self.charset)
                return rsp

    def post_json(self, url, data, headers={}):
        http_headers = {'Encoding': self.charset,
                        'Content-Type': 'application/json'}

        for k, v in headers.items():
            http_headers[k] = v

        rsp = self.http_request(url, 'POST', http_headers, data)
        logging.info('rsp:%s', rsp)
        return json.loads(rsp)

    def my_roles(self, tenant_id: str, login_name: str, password: str):
        md5 = hashlib.md5()
        md5.update(password.encode(self.charset))
        pwd_md5 = md5.hexdigest()
        req = {'loginName': login_name,
               'pwd': pwd_md5,
               'tenantId': tenant_id,
               'forAccessToken': True}
        return self.post_json(self.bbp_base_url + SsdevClient.MY_ROLES_PATH, req)

    def fetch_token(self, tenant_id: str, login_name: str, role: dict):
        req = {'loginName': login_name,
               'tenantId': tenant_id
               }
        self.post_json(self.bbp_base_url + SsdevClient.LOGON_LOGIN_VALIDATE, req)
        token_url = self.bbp_base_url + SsdevClient.MY_APPS + '?'
        urt = role['id']
        ud_id = role['ud_id']
        urt_dept = ud_id if ud_id != urt else ''
        params = {'urt': urt,
                  'deep': '3',
                  'platform': '256',
                  'urtDept': urt_dept
                  }
        token_url = token_url + urllib.parse.urlencode(params)
        logging.info("my app url %s", token_url)
        self.http_request(token_url, 'GET', {}, None)
        for item in self.cookie:
            if 'tk' == item.name:
                self.token = item.value
        return self.token

    def invoke(self, service_id: str, method: str, *args):
        url = self.app_base_url + '/*.jsonRequest'

        headers = {'X-Service-Id': service_id,
                   'X-Service-Method': method,
                   'Encoding': self.charset,
                   'Content-Type': 'application/json'}
        # if self.token is not None:
        #    headers['Cookie'] = 'tk=' + self.token
        if args is None:
            args = []

        return self.post_json(url, args, headers)


